package com.deepwiki.storage.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.transport.endpoints.BooleanResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.stream.Collectors;

/**
 * Elasticsearch存储服务 - 修正版
 * 统一的存储后端，提供所有文档和数据存储功能
 * 基于OpenDeepWiki数据库表结构映射设计
 */
@Component
public class ElasticsearchStorageStrategy {

    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchStorageStrategy.class);
    
    // 索引名称定义 - 修正版
    private static final String DOCUMENT_INDEX = "deepwiki_documents";     // 映射DocumentFileItems表
    private static final String CATALOG_INDEX = "deepwiki_catalogs";       // 合并DocumentCatalogs+Documents表
    private static final String WAREHOUSE_INDEX = "deepwiki_warehouses";   // 映射Warehouses表
    private static final String OVERVIEW_INDEX = "deepwiki_overviews";     // 映射DocumentOverviews表
    private static final String COMMIT_INDEX = "deepwiki_commits";         // 映射DocumentCommitRecords表
    
    // 删除的索引：
    // private static final String TREE_INDEX = "deepwiki_trees";          // 功能重复，已删除
    // private static final String PROCESS_DATA_INDEX = "deepwiki_process_data"; // 职责不明确，已删除

    private final ElasticsearchClient elasticsearchClient;
    private final ObjectMapper objectMapper;

    @Autowired
    public ElasticsearchStorageStrategy(ElasticsearchClient elasticsearchClient, ObjectMapper objectMapper) {
        this.elasticsearchClient = elasticsearchClient;
        this.objectMapper = objectMapper;
        
        // 初始化索引
        initializeIndices();
    }

    /**
     * 保存文档内容 - 映射DocumentFileItems表
     */
    public void saveDocument(String warehouseId, DocumentInfo document) {
        try {
            document.warehouseId = warehouseId;
            document.createdAt = System.currentTimeMillis();

            IndexRequest<DocumentInfo> request = IndexRequest.of(i -> i
                    .index(DOCUMENT_INDEX)
                    .id(generateDocumentKey(warehouseId, document.documentId))
                    .document(document)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("文档保存到ES成功: warehouseId={}, documentId={}, result={}", 
                        warehouseId, document.documentId, response.result());

        } catch (IOException e) {
            logger.error("保存文档到ES失败: warehouseId={}, documentId={}", warehouseId, document.documentId, e);
            throw new RuntimeException("ES保存失败: " + e.getMessage(), e);
        }
    }

    /**
     * 兼容原有的saveMarkdown方法
     */
    public void saveMarkdown(String warehouseId, String documentId, String content) {
        DocumentInfo document = new DocumentInfo();
        document.documentId = documentId;
        document.content = content;
        document.title = ""; // 默认值
        document.description = ""; // 默认值
        saveDocument(warehouseId, document);
    }

    /**
     * 读取文档内容
     */
    public String readMarkdown(String warehouseId, String documentId) {
        try {
            String docKey = generateDocumentKey(warehouseId, documentId);
            
            GetRequest request = GetRequest.of(g -> g
                    .index(DOCUMENT_INDEX)
                    .id(docKey)
            );

            GetResponse<DocumentInfo> response = elasticsearchClient.get(request, DocumentInfo.class);
            
            if (response.found()) {
                return response.source().content;
            } else {
                logger.warn("ES中未找到文档: warehouseId={}, documentId={}", warehouseId, documentId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES读取文档失败: warehouseId={}, documentId={}", warehouseId, documentId, e);
            throw new RuntimeException("ES读取失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存目录信息 - 合并DocumentCatalogs和Documents表
     */
    public void saveCatalog(String warehouseId, CatalogInfo catalog) {
        try {
            catalog.warehouseId = warehouseId;
            catalog.createdAt = System.currentTimeMillis();

            IndexRequest<CatalogInfo> request = IndexRequest.of(i -> i
                    .index(CATALOG_INDEX)
                    .id(generateCatalogKey(warehouseId, catalog.catalogId))
                    .document(catalog)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("目录保存到ES成功: warehouseId={}, catalogId={}", warehouseId, catalog.catalogId);

        } catch (IOException e) {
            logger.error("保存目录到ES失败: warehouseId={}, catalogId={}", warehouseId, catalog.catalogId, e);
            throw new RuntimeException("ES保存目录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存仓库元数据 - 映射Warehouses表
     */
    public void saveWarehouse(WarehouseInfo warehouse) {
        try {
            warehouse.createdAt = System.currentTimeMillis();

            IndexRequest<WarehouseInfo> request = IndexRequest.of(i -> i
                    .index(WAREHOUSE_INDEX)
                    .id(warehouse.warehouseId)
                    .document(warehouse)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("仓库元数据保存到ES成功: warehouseId={}", warehouse.warehouseId);

        } catch (IOException e) {
            logger.error("保存仓库元数据到ES失败: warehouseId={}", warehouse.warehouseId, e);
            throw new RuntimeException("ES保存仓库元数据失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存文档概览 - 映射DocumentOverviews表
     */
    public void saveOverview(String warehouseId, OverviewInfo overview) {
        try {
            overview.warehouseId = warehouseId;
            overview.createdAt = System.currentTimeMillis();

            IndexRequest<OverviewInfo> request = IndexRequest.of(i -> i
                    .index(OVERVIEW_INDEX)
                    .id(generateOverviewKey(warehouseId, overview.overviewId))
                    .document(overview)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("概览保存到ES成功: warehouseId={}, overviewId={}", warehouseId, overview.overviewId);

        } catch (IOException e) {
            logger.error("保存概览到ES失败: warehouseId={}, overviewId={}", warehouseId, overview.overviewId, e);
            throw new RuntimeException("ES保存概览失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存提交记录 - 映射DocumentCommitRecords表
     */
    public void saveCommit(String warehouseId, CommitInfo commit) {
        try {
            commit.warehouseId = warehouseId;
            commit.lastUpdate = System.currentTimeMillis();

            IndexRequest<CommitInfo> request = IndexRequest.of(i -> i
                    .index(COMMIT_INDEX)
                    .id(generateCommitKey(warehouseId, commit.commitId))
                    .document(commit)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("提交记录保存到ES成功: warehouseId={}, commitId={}", warehouseId, commit.commitId);

        } catch (IOException e) {
            logger.error("保存提交记录到ES失败: warehouseId={}, commitId={}", warehouseId, commit.commitId, e);
            throw new RuntimeException("ES保存提交记录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 兼容方法：保存目录树（现在保存到仓库的optimizedDirectoryStructure字段）
     */
    public void saveDirectoryTree(String warehouseId, String treeJson) {
        try {
            // 获取现有仓库信息
            GetRequest getRequest = GetRequest.of(g -> g
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            GetResponse<WarehouseInfo> getResponse = elasticsearchClient.get(getRequest, WarehouseInfo.class);
            
            WarehouseInfo warehouse;
            if (getResponse.found()) {
                warehouse = getResponse.source();
            } else {
                warehouse = new WarehouseInfo();
                warehouse.warehouseId = warehouseId;
                warehouse.name = "";
                warehouse.description = "";
            }
            
            // 更新目录树结构
            warehouse.optimizedDirectoryStructure = treeJson;
            saveWarehouse(warehouse);
            
            logger.debug("目录树保存到仓库成功: warehouseId={}", warehouseId);

        } catch (IOException e) {
            logger.error("保存目录树失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES保存目录树失败: " + e.getMessage(), e);
        }
    }

    /**
     * 兼容方法：读取目录树
     */
    public String readDirectoryTree(String warehouseId) {
        try {
            GetRequest request = GetRequest.of(g -> g
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            GetResponse<WarehouseInfo> response = elasticsearchClient.get(request, WarehouseInfo.class);
            
            if (response.found() && response.source().optimizedDirectoryStructure != null) {
                return response.source().optimizedDirectoryStructure;
            } else {
                logger.warn("ES中未找到目录树: warehouseId={}", warehouseId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES读取目录树失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES读取目录树失败: " + e.getMessage(), e);
        }
    }

    public boolean exists(String warehouseId, String documentId) {
        try {
            String docKey = generateDocumentKey(warehouseId, documentId);
            
            ExistsRequest request = ExistsRequest.of(e -> e
                    .index(DOCUMENT_INDEX)
                    .id(docKey)
            );

            BooleanResponse response = elasticsearchClient.exists(request);
            return response.value();

        } catch (IOException e) {
            logger.error("检查ES文档存在性失败: warehouseId={}, documentId={}", warehouseId, documentId, e);
            return false;
        }
    }

    public void deleteWarehouseData(String warehouseId) {
        try {
            // 删除所有相关文档
            DeleteByQueryRequest deleteDocsRequest = DeleteByQueryRequest.of(d -> d
                    .index(DOCUMENT_INDEX)
                    .query(q -> q.term(t -> t.field("warehouseId").value(warehouseId)))
            );

            DeleteByQueryResponse deleteDocsResponse = elasticsearchClient.deleteByQuery(deleteDocsRequest);
            logger.info("删除ES仓库文档成功: warehouseId={}, deleted={}", warehouseId, deleteDocsResponse.deleted());

            // 删除目录树
            DeleteRequest deleteTreeRequest = DeleteRequest.of(d -> d
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            try {
                DeleteResponse deleteTreeResponse = elasticsearchClient.delete(deleteTreeRequest);
                logger.info("删除ES目录树成功: warehouseId={}, result={}", warehouseId, deleteTreeResponse.result());
            } catch (Exception e) {
                logger.warn("删除ES目录树失败(可能不存在): warehouseId={}", warehouseId);
            }

        } catch (IOException e) {
            logger.error("删除ES仓库数据失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES删除失败: " + e.getMessage(), e);
        }
    }

    public List<String> listDocuments(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(DOCUMENT_INDEX)
                    .query(q -> q.term(t -> t.field("warehouseId").value(warehouseId)))
                    .source(so -> so.filter(f -> f.includes("documentId")))
                    .size(1000)
            );

            SearchResponse<Map> response = elasticsearchClient.search(request, Map.class);
            
            return response.hits().hits().stream()
                    .map(hit -> (String) hit.source().get("documentId"))
                    .toList();

        } catch (IOException e) {
            logger.error("列出ES文档失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES列出文档失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存仓库过程数据
     */
    public void saveProcessData(String warehouseId, String dataType, String dataKey, String data, Map<String, Object> metadata) {
        try {
            ProcessDataInfo processData = new ProcessDataInfo();
            processData.warehouseId = warehouseId;
            processData.dataType = dataType;
            processData.dataKey = dataKey;
            processData.data = data;
            processData.metadata = metadata;
            processData.timestamp = System.currentTimeMillis();

            IndexRequest<ProcessDataInfo> request = IndexRequest.of(i -> i
                    .index(PROCESS_DATA_INDEX)
                    .id(generateProcessDataKey(warehouseId, dataType, dataKey))
                    .document(processData)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("过程数据保存到ES成功: warehouseId={}, dataType={}, dataKey={}", 
                        warehouseId, dataType, dataKey);

        } catch (IOException e) {
            logger.error("保存过程数据到ES失败: warehouseId={}, dataType={}, dataKey={}", 
                        warehouseId, dataType, dataKey, e);
            throw new RuntimeException("ES保存过程数据失败: " + e.getMessage(), e);
        }
    }

    /**
     * 读取过程数据
     */
    public String readProcessData(String warehouseId, String dataType, String dataKey) {
        try {
            String key = generateProcessDataKey(warehouseId, dataType, dataKey);
            
            GetRequest request = GetRequest.of(g -> g
                    .index(PROCESS_DATA_INDEX)
                    .id(key)
            );

            GetResponse<ProcessDataInfo> response = elasticsearchClient.get(request, ProcessDataInfo.class);
            
            if (response.found()) {
                return response.source().data;
            } else {
                logger.warn("ES中未找到过程数据: warehouseId={}, dataType={}, dataKey={}", 
                           warehouseId, dataType, dataKey);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES读取过程数据失败: warehouseId={}, dataType={}, dataKey={}", 
                        warehouseId, dataType, dataKey, e);
            throw new RuntimeException("ES读取过程数据失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存文档目录结构（包含完整目录树信息，避免递归查询）
     */
    public void saveDocumentCatalog(String warehouseId, String catalogId, String parentId, 
                                   String name, String description, String url, String prompt,
                                   Integer orderIndex, String contentPath, Boolean isGenerated,
                                   String fullPath, String treeStructure) {
        try {
            DocumentCatalogInfo catalog = new DocumentCatalogInfo();
            catalog.warehouseId = warehouseId;
            catalog.catalogId = catalogId;
            catalog.parentId = parentId;
            catalog.name = name;
            catalog.description = description;
            catalog.url = url;
            catalog.prompt = prompt;
            catalog.orderIndex = orderIndex;
            catalog.contentPath = contentPath;
            catalog.isGenerated = isGenerated;
            catalog.fullPath = fullPath; // 完整路径，如：root/chapter1/section1.1
            catalog.treeStructure = treeStructure; // JSON格式的树结构，避免递归查询
            catalog.timestamp = System.currentTimeMillis();

            IndexRequest<DocumentCatalogInfo> request = IndexRequest.of(i -> i
                    .index(CATALOG_INDEX)
                    .id(generateCatalogKey(warehouseId, catalogId))
                    .document(catalog)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("文档目录保存到ES成功: warehouseId={}, catalogId={}", warehouseId, catalogId);

        } catch (IOException e) {
            logger.error("保存文档目录到ES失败: warehouseId={}, catalogId={}", warehouseId, catalogId, e);
            throw new RuntimeException("ES保存文档目录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 保存仓库元数据（包含目录树快照避免递归查询）
     */
    public void saveWarehouseMetadata(String warehouseId, String name, String description, 
                                     String localPath, String status, String directoryTreeSnapshot) {
        try {
            WarehouseMetadataInfo warehouse = new WarehouseMetadataInfo();
            warehouse.warehouseId = warehouseId;
            warehouse.name = name;
            warehouse.description = description;
            warehouse.localPath = localPath;
            warehouse.status = status;
            warehouse.directoryTreeSnapshot = directoryTreeSnapshot; // 目录树快照，避免递归查询
            warehouse.timestamp = System.currentTimeMillis();

            IndexRequest<WarehouseMetadataInfo> request = IndexRequest.of(i -> i
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
                    .document(warehouse)
            );

            IndexResponse response = elasticsearchClient.index(request);
            logger.debug("仓库元数据保存到ES成功: warehouseId={}", warehouseId);

        } catch (IOException e) {
            logger.error("保存仓库元数据到ES失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES保存仓库元数据失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取仓库的完整目录树（通过快照，无需递归）
     */
    public String getWarehouseDirectoryTreeSnapshot(String warehouseId) {
        try {
            GetRequest request = GetRequest.of(g -> g
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            GetResponse<WarehouseMetadataInfo> response = elasticsearchClient.get(request, WarehouseMetadataInfo.class);
            
            if (response.found()) {
                return response.source().directoryTreeSnapshot;
            } else {
                logger.warn("ES中未找到仓库元数据: warehouseId={}", warehouseId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES读取仓库目录树快照失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES读取目录树快照失败: " + e.getMessage(), e);
        }
    }

    /**
     * 查询文档目录（按层级，支持快速检索）
     */
    public List<DocumentCatalogInfo> getCatalogsByWarehouse(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(CATALOG_INDEX)
                    .query(q -> q.term(t -> t.field("warehouseId").value(warehouseId)))
                    .sort(sort -> sort.field(f -> f.field("orderIndex").order(SortOrder.Asc)))
                    .size(1000)
            );

            SearchResponse<DocumentCatalogInfo> response = elasticsearchClient.search(request, DocumentCatalogInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .toList();

        } catch (IOException e) {
            logger.error("查询文档目录失败: warehouseId={}", warehouseId, e);
            throw new RuntimeException("ES查询文档目录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取仓库信息
     */
    public WarehouseInfo getWarehouse(String warehouseId) {
        try {
            GetRequest request = GetRequest.of(g -> g
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            GetResponse<WarehouseInfo> response = elasticsearchClient.get(request, WarehouseInfo.class);
            
            if (response.found()) {
                return response.source();
            } else {
                logger.warn("ES中未找到仓库: {}", warehouseId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES获取仓库失败: {}", warehouseId, e);
            return null;
        }
    }

    /**
     * 获取所有仓库
     */
    public List<WarehouseInfo> getAllWarehouses() {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(WAREHOUSE_INDEX)
                    .query(q -> q.bool(b -> b
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .size(1000)
            );

            SearchResponse<WarehouseInfo> response = elasticsearchClient.search(request, WarehouseInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("从ES获取所有仓库失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 检查仓库是否存在
     */
    public boolean warehouseExists(String address) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(WAREHOUSE_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.term(t -> t.field("address").value(address)))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .size(1)
            );

            SearchResponse<WarehouseInfo> response = elasticsearchClient.search(request, WarehouseInfo.class);
            
            return response.hits().total().value() > 0;

        } catch (IOException e) {
            logger.error("检查仓库是否存在失败: {}", address, e);
            return false;
        }
    }

    /**
     * 获取仓库的文档目录结构
     */
    public String getDocumentTreeStructure(String warehouseId) {
        try {
            GetRequest request = GetRequest.of(g -> g
                    .index(WAREHOUSE_INDEX)
                    .id(warehouseId)
            );

            GetResponse<WarehouseInfo> response = elasticsearchClient.get(request, WarehouseInfo.class);
            
            if (response.found() && response.source().documentTreeStructure != null) {
                return response.source().documentTreeStructure;
            } else {
                logger.warn("ES中未找到仓库的文档目录结构: {}", warehouseId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES获取文档目录结构失败: {}", warehouseId, e);
            return null;
        }
    }

    /**
     * 获取仓库的目录列表
     */
    public List<CatalogInfo> getCatalogsByWarehouse(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(CATALOG_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.term(t -> t.field("warehouseId").value(warehouseId)))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .sort(sort -> sort.field(f -> f.field("orderIndex").order(SortOrder.Asc)))
                    .size(1000)
            );

            SearchResponse<CatalogInfo> response = elasticsearchClient.search(request, CatalogInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("查询仓库目录列表失败: {}", warehouseId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 根据状态获取仓库列表
     */
    public List<WarehouseInfo> getWarehousesByStatus(String status) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(WAREHOUSE_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.term(t -> t.field("status").value(status)))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .size(1000)
            );

            SearchResponse<WarehouseInfo> response = elasticsearchClient.search(request, WarehouseInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("根据状态获取仓库失败: {}", status, e);
            return new ArrayList<>();
        }
    }

    /**
     * 搜索仓库
     */
    public List<WarehouseInfo> searchWarehouses(String keyword) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(WAREHOUSE_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.multiMatch(mm -> mm
                                    .query(keyword)
                                    .fields("name", "description", "organizationName")
                            ))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .size(100)
            );

            SearchResponse<WarehouseInfo> response = elasticsearchClient.search(request, WarehouseInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("搜索仓库失败: {}", keyword, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取仓库统计信息
     */
    public Map<String, Long> getWarehouseStats() {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(WAREHOUSE_INDEX)
                    .query(q -> q.bool(b -> b
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .aggregations("status_counts", a -> a
                            .terms(t -> t.field("status"))
                    )
                    .size(0)
            );

            SearchResponse<WarehouseInfo> response = elasticsearchClient.search(request, WarehouseInfo.class);
            
            Map<String, Long> stats = new HashMap<>();
            
            if (response.aggregations() != null && response.aggregations().get("status_counts") != null) {
                var statusAgg = response.aggregations().get("status_counts").sterms();
                
                long totalCount = 0;
                for (var bucket : statusAgg.buckets().array()) {
                    String status = bucket.key().stringValue().toLowerCase();
                    Long count = bucket.docCount();
                    stats.put(status, count);
                    totalCount += count;
                }
                stats.put("total", totalCount);
            }
            
            return stats;

        } catch (IOException e) {
            logger.error("获取仓库统计信息失败", e);
            return new HashMap<>();
        }
    }

    /**
     * 获取文档记录（通过仓库ID）
     */
    public CommitInfo getDocumentByWarehouseId(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(COMMIT_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.term(t -> t.field("warehouseId").value(warehouseId)))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .size(1)
            );

            SearchResponse<CommitInfo> response = elasticsearchClient.search(request, CommitInfo.class);
            
            if (response.hits().total().value() > 0) {
                return response.hits().hits().get(0).source();
            } else {
                return null;
            }

        } catch (IOException e) {
            logger.error("获取文档记录失败: {}", warehouseId, e);
            return null;
        }
    }

    /**
     * 获取文档详细信息
     */
    public DocumentInfo getDocumentInfo(String warehouseId, String documentId) {
        try {
            String docKey = generateDocumentKey(warehouseId, documentId);
            
            GetRequest request = GetRequest.of(g -> g
                    .index(DOCUMENT_INDEX)
                    .id(docKey)
            );

            GetResponse<DocumentInfo> response = elasticsearchClient.get(request, DocumentInfo.class);
            
            if (response.found()) {
                return response.source();
            } else {
                logger.warn("ES中未找到文档: {}/{}", warehouseId, documentId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES获取文档详细信息失败: {}/{}", warehouseId, documentId, e);
            return null;
        }
    }

    /**
     * 获取目录详细信息
     */
    public CatalogInfo getCatalogInfo(String warehouseId, String catalogId) {
        try {
            String catalogKey = generateCatalogKey(warehouseId, catalogId);
            
            GetRequest request = GetRequest.of(g -> g
                    .index(CATALOG_INDEX)
                    .id(catalogKey)
            );

            GetResponse<CatalogInfo> response = elasticsearchClient.get(request, CatalogInfo.class);
            
            if (response.found()) {
                return response.source();
            } else {
                logger.warn("ES中未找到目录: {}/{}", warehouseId, catalogId);
                return null;
            }

        } catch (IOException e) {
            logger.error("从ES获取目录详细信息失败: {}/{}", warehouseId, catalogId, e);
            return null;
        }
    }

    /**
     * 获取仓库的文档概览列表
     */
    public List<OverviewInfo> getOverviewsByWarehouse(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(OVERVIEW_INDEX)
                    .query(q -> q.term(t -> t.field("warehouseId").value(warehouseId)))
                    .sort(sort -> sort.field(f -> f.field("createdAt").order(SortOrder.Desc)))
                    .size(100)
            );

            SearchResponse<OverviewInfo> response = elasticsearchClient.search(request, OverviewInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("查询仓库概览列表失败: {}", warehouseId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取仓库的提交记录列表
     */
    public List<CommitInfo> getCommitsByWarehouse(String warehouseId) {
        try {
            SearchRequest request = SearchRequest.of(s -> s
                    .index(COMMIT_INDEX)
                    .query(q -> q.bool(b -> b
                            .must(m -> m.term(t -> t.field("warehouseId").value(warehouseId)))
                            .mustNot(mn -> mn.term(t -> t.field("isDeleted").value(true)))
                    ))
                    .sort(sort -> sort.field(f -> f.field("lastUpdate").order(SortOrder.Desc)))
                    .size(100)
            );

            SearchResponse<CommitInfo> response = elasticsearchClient.search(request, CommitInfo.class);
            
            return response.hits().hits().stream()
                    .map(hit -> hit.source())
                    .collect(Collectors.toList());

        } catch (IOException e) {
            logger.error("查询仓库提交记录失败: {}", warehouseId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 初始化ES索引
     */
    private void initializeIndices() {
        try {
            // 创建文档索引 - 映射DocumentFileItems
            createIndexIfNotExists(DOCUMENT_INDEX, getDocumentIndexMapping());
            
            // 创建目录索引 - 合并DocumentCatalogs+Documents  
            createIndexIfNotExists(CATALOG_INDEX, getCatalogIndexMapping());

            // 创建仓库元数据索引 - 映射Warehouses
            createIndexIfNotExists(WAREHOUSE_INDEX, getWarehouseIndexMapping());

            // 创建概览索引 - 映射DocumentOverviews
            createIndexIfNotExists(OVERVIEW_INDEX, getOverviewIndexMapping());

            // 创建提交记录索引 - 映射DocumentCommitRecords
            createIndexIfNotExists(COMMIT_INDEX, getCommitIndexMapping());
            
        } catch (IOException e) {
            logger.error("初始化ES索引失败", e);
            throw new RuntimeException("ES索引初始化失败: " + e.getMessage(), e);
        }
    }

    /**
     * 如果索引不存在则创建
     */
    private void createIndexIfNotExists(String indexName, String mapping) throws IOException {
        ExistsRequest existsRequest = ExistsRequest.of(e -> e.index(indexName));
        BooleanResponse exists = elasticsearchClient.indices().exists(existsRequest);

        if (!exists.value()) {
            CreateIndexRequest createRequest = CreateIndexRequest.of(c -> c
                    .index(indexName)
                    .withJson(new StringReader(mapping))
            );

            elasticsearchClient.indices().create(createRequest);
            logger.info("ES索引创建成功: {}", indexName);
        }
    }

    /**
     * 文档索引映射 - 映射DocumentFileItems表
     */
    private String getDocumentIndexMapping() {
        return """
                {
                  "mappings": {
                    "properties": {
                      "warehouseId": {
                        "type": "keyword"
                      },
                      "documentId": {
                        "type": "keyword"
                      },
                      "catalogId": {
                        "type": "keyword"
                      },
                      "title": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "description": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "content": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "size": {
                        "type": "long"
                      },
                      "commentCount": {
                        "type": "long"
                      },
                      "requestToken": {
                        "type": "integer"
                      },
                      "responseToken": {
                        "type": "integer"
                      },
                      "isEmbedded": {
                        "type": "boolean"
                      },
                      "metadata": {
                        "type": "object",
                        "dynamic": true
                      },
                      "extra": {
                        "type": "object",
                        "dynamic": true
                      },
                      "sources": {
                        "type": "nested",
                        "properties": {
                          "name": {
                            "type": "keyword"
                          },
                          "address": {
                            "type": "keyword"
                          }
                        }
                      },
                      "createdAt": {
                        "type": "long"
                      }
                    }
                  }
                }
                """;
    }

    /**
     * 目录索引映射 - 合并DocumentCatalogs和Documents表
     */
    private String getCatalogIndexMapping() {
        return """
                {
                  "mappings": {
                    "properties": {
                      "warehouseId": {
                        "type": "keyword"
                      },
                      "catalogId": {
                        "type": "keyword"
                      },
                      "documentId": {
                        "type": "keyword"
                      },
                      "parentId": {
                        "type": "keyword"
                      },
                      "name": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "url": {
                        "type": "keyword"
                      },
                      "description": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "orderIndex": {
                        "type": "integer"
                      },
                      "isCompleted": {
                        "type": "boolean"
                      },
                      "isDeleted": {
                        "type": "boolean"
                      },
                      "prompt": {
                        "type": "text",
                        "index": false
                      },
                      "dependentFile": {
                        "type": "keyword"
                      },
                      "gitPath": {
                        "type": "keyword"
                      },
                      "status": {
                        "type": "keyword"
                      },
                      "likeCount": {
                        "type": "long"
                      },
                      "commentCount": {
                        "type": "long"
                      },
                      "lastUpdate": {
                        "type": "long"
                      },
                      "fullPath": {
                        "type": "keyword"
                      },
                      "level": {
                        "type": "integer"
                      },
                      "createdAt": {
                        "type": "long"
                      }
                    }
                  }
                }
                """;
    }

    /**
     * 仓库元数据索引映射 - 映射Warehouses表
     */
    private String getWarehouseIndexMapping() {
        return """
                {
                  "mappings": {
                    "properties": {
                      "warehouseId": {
                        "type": "keyword"
                      },
                      "organizationName": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "name": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "description": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "address": {
                        "type": "keyword"
                      },
                      "type": {
                        "type": "keyword"
                      },
                      "branch": {
                        "type": "keyword"
                      },
                      "status": {
                        "type": "keyword"
                      },
                      "error": {
                        "type": "text",
                        "index": false
                      },
                      "prompt": {
                        "type": "text",
                        "index": false
                      },
                      "version": {
                        "type": "keyword"
                      },
                      "model": {
                        "type": "keyword"
                      },
                      "isEmbedded": {
                        "type": "boolean"
                      },
                      "isRecommended": {
                        "type": "boolean"
                      },
                      "optimizedDirectoryStructure": {
                        "type": "text",
                        "index": false
                      },
                      "documentTreeStructure": {
                        "type": "text",
                        "index": false
                      },
                      "createdAt": {
                        "type": "long"
                      }
                    }
                  }
                }
                """;
    }

    /**
     * 概览索引映射 - 映射DocumentOverviews表
     */
    private String getOverviewIndexMapping() {
        return """
                {
                  "mappings": {
                    "properties": {
                      "overviewId": {
                        "type": "keyword"
                      },
                      "documentId": {
                        "type": "keyword"
                      },
                      "warehouseId": {
                        "type": "keyword"
                      },
                      "title": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "content": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "createdAt": {
                        "type": "long"
                      }
                    }
                  }
                }
                """;
    }

    /**
     * 提交记录索引映射 - 映射DocumentCommitRecords表
     */
    private String getCommitIndexMapping() {
        return """
                {
                  "mappings": {
                    "properties": {
                      "commitRecordId": {
                        "type": "keyword"
                      },
                      "warehouseId": {
                        "type": "keyword"
                      },
                      "commitId": {
                        "type": "keyword"
                      },
                      "commitMessage": {
                        "type": "text",
                        "analyzer": "standard"
                      },
                      "title": {
                        "type": "text",
                        "analyzer": "standard",
                        "fields": {
                          "keyword": {
                            "type": "keyword"
                          }
                        }
                      },
                      "author": {
                        "type": "keyword"
                      },
                      "lastUpdate": {
                        "type": "long"
                      }
                    }
                  }
                }
                """;
    }

    /**
     * 生成文档键
     */
    private String generateDocumentKey(String warehouseId, String documentId) {
        return warehouseId + ":" + documentId;
    }

    /**
     * 生成目录键
     */
    private String generateCatalogKey(String warehouseId, String catalogId) {
        return warehouseId + ":" + catalogId;
    }

    /**
     * 生成概览键
     */
    private String generateOverviewKey(String warehouseId, String overviewId) {
        return warehouseId + ":" + overviewId;
    }

    /**
     * 生成提交记录键
     */
    private String generateCommitKey(String warehouseId, String commitId) {
        return warehouseId + ":" + commitId;
    }

    /**
     * 文档信息类 - 映射DocumentFileItems表
     */
    public static class DocumentInfo {
        public String warehouseId;           // 从DocumentCatalogs关联获取
        public String documentId;            // DocumentFileItems.Id
        public String catalogId;             // DocumentFileItems.DocumentCatalogId
        public String title;                 // DocumentFileItems.Title
        public String description;           // DocumentFileItems.Description
        public String content;               // DocumentFileItems.Content
        public Long size;                    // DocumentFileItems.Size
        public Long commentCount;            // DocumentFileItems.CommentCount
        public Integer requestToken;         // DocumentFileItems.RequestToken
        public Integer responseToken;        // DocumentFileItems.ResponseToken
        public Boolean isEmbedded;           // DocumentFileItems.IsEmbedded
        public Map<String, Object> metadata; // DocumentFileItems.Metadata
        public Map<String, Object> extra;    // DocumentFileItems.Extra
        public List<SourceInfo> sources;     // DocumentFileItemSources集合
        public Long createdAt;               // DocumentFileItems.CreatedAt
    }

    /**
     * 文档来源信息类 - 映射DocumentFileItemSources表
     */
    public static class SourceInfo {
        public String name;                  // DocumentFileItemSources.Name
        public String address;               // DocumentFileItemSources.Address
    }

    /**
     * 目录信息类 - 合并DocumentCatalogs和Documents表
     */
    public static class CatalogInfo {
        public String warehouseId;           // DocumentCatalogs.WarehouseId
        public String catalogId;             // DocumentCatalogs.Id
        public String documentId;            // DocumentCatalogs.DucumentId
        public String parentId;              // DocumentCatalogs.ParentId
        public String name;                  // DocumentCatalogs.Name
        public String url;                   // DocumentCatalogs.Url
        public String description;           // 合并两表的Description
        public Integer orderIndex;           // DocumentCatalogs.Order
        public Boolean isCompleted;          // DocumentCatalogs.IsCompleted
        public Boolean isDeleted;            // DocumentCatalogs.IsDeleted
        public String prompt;                // DocumentCatalogs.Prompt
        public String dependentFile;         // DocumentCatalogs.DependentFile
        // Documents表字段
        public String gitPath;               // Documents.GitPath
        public String status;                // Documents.Status
        public Long likeCount;               // Documents.LikeCount
        public Long commentCount;            // Documents.CommentCount
        public Long lastUpdate;              // Documents.LastUpdate
        // 优化字段
        public String fullPath;              // 计算字段，完整路径
        public Integer level;                // 计算字段，层级深度
        public Long createdAt;               // DocumentCatalogs.CreatedAt
    }

    /**
     * 仓库信息类 - 映射Warehouses表
     */
    public static class WarehouseInfo {
        public String warehouseId;                      // Warehouses.Id
        public String organizationName;                 // Warehouses.OrganizationName
        public String name;                            // Warehouses.Name
        public String description;                     // Warehouses.Description
        public String address;                         // Warehouses.Address
        public String type;                            // Warehouses.Type
        public String branch;                          // Warehouses.Branch
        public String gitUsername;                     // Warehouses.GitUsername
        public String gitPassword;                     // Warehouses.GitPassword
        public String email;                           // Warehouses.Email
        public String status;                          // Warehouses.Status
        public String error;                           // Warehouses.Error
        public String prompt;                          // Warehouses.Prompt
        public String version;                         // Warehouses.Version
        public String model;                           // Warehouses.Model
        public Boolean isEmbedded;                     // Warehouses.IsEmbedded
        public Boolean isRecommended;                  // Warehouses.IsRecommended
        public Boolean isDeleted;                      // Warehouses.IsDeleted
        public String optimizedDirectoryStructure;     // Warehouses.OptimizedDirectoryStructure - AI优化后的代码文件目录结构
        public String documentTreeStructure;           // 生成的markdown文档目录结构JSON，用于前端wiki导航
        public Long createdAt;                         // Warehouses.CreatedAt
    }

    /**
     * 概览信息类 - 映射DocumentOverviews表
     */
    public static class OverviewInfo {
        public String overviewId;            // DocumentOverviews.Id
        public String documentId;            // DocumentOverviews.DocumentId
        public String warehouseId;           // 通过Documents表关联获取
        public String title;                 // DocumentOverviews.Title
        public String content;               // DocumentOverviews.Content
        public Long createdAt;               // DocumentOverviews.CreatedAt
    }

    /**
     * 提交记录信息类 - 映射DocumentCommitRecords表
     */
    public static class CommitInfo {
        public String commitRecordId;        // DocumentCommitRecords.Id
        public String warehouseId;           // DocumentCommitRecords.WarehouseId
        public String commitId;              // DocumentCommitRecords.CommitId
        public String documentId;            // 关联的文档ID
        public String gitPath;               // Documents.GitPath
        public String status;                // Documents.Status
        public String commitMessage;         // DocumentCommitRecords.CommitMessage
        public String title;                 // DocumentCommitRecords.Title
        public String author;                // DocumentCommitRecords.Author
        public Long likeCount;               // Documents.LikeCount
        public Long commentCount;            // Documents.CommentCount
        public Long lastUpdate;              // DocumentCommitRecords.LastUpdate
        public Boolean isDeleted;            // Documents.IsDeleted
    }
} 